package com.utils;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ReflectUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.dto.BasePage;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class BeanConvertUtil {
    private BeanConvertUtil() {
    }

    public static void copyProperties(Object source, Object target, String... ignoreProperties) {
        BeanUtil.copyProperties(source, target, ignoreProperties);
    }

    public static void copyProperties(Object source, Object target, Map<String, String> fieldMapping, String... ignoreProperties) {
        CopyOptions options = CopyOptions.create().setIgnoreProperties(ignoreProperties).setFieldMapping(fieldMapping);
        BeanUtil.copyProperties(source, target, options);
    }

    public static <S, T> BasePage<T> copyPageBeanProperties(IPage<S> source, BasePage<T> target, Class<T> targetType) {
        copyPageBeanProperties(source, target);
        if (CollUtil.isNotEmpty(source.getRecords())) {
            List<T> recordList = BeanUtil.copyToList(source.getRecords(), targetType);
            target.setRecords(recordList);
        }

        return target;
    }

    public static <S, T> BasePage<T> copyPageBeanProperties(IPage<S> source, BasePage<T> target, Class<T> targetType, Map<String, String> fieldMapping) {
        copyPageBeanProperties(source, target, fieldMapping);
        if (CollUtil.isNotEmpty(source.getRecords())) {
            CopyOptions options = CopyOptions.create().setFieldMapping(fieldMapping);
            List<T> recordList = BeanUtil.copyToList(source.getRecords(), targetType, options);
            target.setRecords(recordList);
        }

        return target;
    }

    public static <S, T> BasePage<T> copyPageBeanProperties(BasePage<S> source, BasePage<T> target, Class<T> targetType, String... ignoreProperties) {
        BeanUtil.copyProperties(source, target, ignoreProperties);
        if (CollUtil.isNotEmpty(source.getRecords())) {
            List<T> recordList = BeanUtil.copyToList(source.getRecords(), targetType);
            target.setRecords(recordList);
        }

        return target;
    }

    public static <S, T> BasePage<T> copyPageBeanProperties(BasePage<S> source, BasePage<T> target, Class<T> targetType, Map<String, String> fieldMapping, String... ignoreProperties) {
        CopyOptions options = CopyOptions.create().setIgnoreProperties(ignoreProperties).setFieldMapping(fieldMapping);
        BeanUtil.copyProperties(source, target, options);
        if (CollUtil.isNotEmpty(source.getRecords())) {
            List<T> recordList = BeanUtil.copyToList(source.getRecords(), targetType, options);
            target.setRecords(recordList);
        }

        return target;
    }

    public static <T> T copyPageBeanProperties(Object source, T target) {
        Map<String, String> fieldMapping = new HashMap(2);
        fieldMapping.put("current", "currentPage");
        fieldMapping.put("size", "pageSize");
        CopyOptions options = CopyOptions.create().setFieldMapping(fieldMapping);
        BeanUtil.copyProperties(source, target, options);
        return target;
    }

    public static <T> T copyPageBeanProperties(Object source, T target, Map<String, String> fieldMapping) {
        fieldMapping.put("current", "currentPage");
        fieldMapping.put("size", "pageSize");
        CopyOptions options = CopyOptions.create().setFieldMapping(fieldMapping);
        BeanUtil.copyProperties(source, target, options);
        return target;
    }

    public static <T> T copyProperties(Object source, Class<T> targetClass, String... ignoreProperties) {
        return (T)BeanUtil.copyProperties(source, targetClass, ignoreProperties);
    }

    public static <T> T copyProperties(Object source, Class<T> targetClass, Map<String, String> fieldMapping, String... ignoreProperties) {
        T target = (T)ReflectUtil.newInstanceIfPossible(targetClass);
        copyProperties(source, target, fieldMapping, ignoreProperties);
        return target;
    }

    public static <S, T> List<T> copyToList(List<S> sourceList, Class<T> targetType) {
        return BeanUtil.copyToList(sourceList, targetType);
    }

    public static <S, T> List<T> copyToList(List<S> sourceList, Class<T> targetType, Map<String, String> fieldMapping) {
        CopyOptions options = CopyOptions.create().setFieldMapping(fieldMapping);
        return BeanUtil.copyToList(sourceList, targetType, options);
    }
}
